import axios from 'axios'
import qs from 'qs'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import type { IRequestConfig, IApiData } from './type'
import { Ui, cache } from '@/utils'
import router from '@/router'

export class Request {
  instance: AxiosInstance
  constructor(config: IRequestConfig) {
    this.instance = axios.create(config)

    /**全局拦截 */

    this.instance.interceptors.request.use(
      config => {
        const token = cache.getToken()
        // token
        if (token) config.headers['token'] = token
        // get请求传数组序列化
        if (config.method === 'get') {
          config.paramsSerializer = params => qs.stringify(params, { arrayFormat: 'indices' })
        }
        return config
      },
      err => {
        return err
      }
    )

    this.instance.interceptors.response.use(
      res => {
        return res.data
      },
      err => {
        const code = err.response.status

        const httpCodeLabel: Record<number, string> = {
          400: '请求参数错误',
          401: '未授权，请登录',
          403: '拒绝访问',
          404: `请求地址出错`,
          408: '请求超时',
          500: 'API接口报500错误',
          501: '服务未实现',
          502: '网关错误',
          503: '服务不可用',
          504: '网关超时',
          505: 'HTTP版本不受支持'
        }
        // eslint-disable-next-line no-console
        console.log(httpCodeLabel[code])
        if (code === 401) {
          cache.clear(true)
          Ui.useMessage('error', httpCodeLabel[code])
          router.push('/login')
        }
        return err
      }
    )

    /**单个实例设置的拦截，可不传 */

    this.instance.interceptors.request.use(config.interceptors?.reqInterceptor, config.interceptors?.reqInterceptorCatch)

    this.instance.interceptors.response.use(config.interceptors?.resInterceptor, config.interceptors?.resInterceptorCatch)
  }

  request<T = any>(config: AxiosRequestConfig) {
    return this.instance.request<any, IApiData<T>>(config)
  }

  get<T = any>(path: string, params?: any, config?: AxiosRequestConfig) {
    return this.request<T>({ ...config, method: 'GET', url: path, params: params })
  }

  post<T = any>(path: string, body?: any, config?: AxiosRequestConfig) {
    return this.request<T>({ ...config, method: 'POST', url: path, data: body })
  }

  put<T = any>(path: string, body?: any, config?: AxiosRequestConfig) {
    return this.request<T>({ ...config, method: 'PUT', url: path, data: body })
  }

  delete<T = any>(path: string, body?: any, config?: AxiosRequestConfig) {
    return this.request<T>({ ...config, method: 'DELETE', url: path, data: body })
  }
}
